package com.example.demo.shiro;

import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 * @Classname shiroConfig
 * @Description TODO
 * @Date 2019/10/23 10:23
 * @Created by yby
 */
//@Configuration
public class shiroConfig {

    //1:配置密码验证器
   /* @Bean("credentialsMatcher")
    public CredentialsMatcher credentialsMatcher(){
        return new MyMatcher();
    }
    //2:配置权限验证器
    @Bean("myRealm")
    public MyRealm myRealm(@Qualifier("credentialsMatcher") CredentialsMatcher credentialsMatcher){
        MyRealm myRealm =new MyRealm();
        //给权限验证器配置上自定义的密码验证器
        myRealm.setCredentialsMatcher(credentialsMatcher);
        return myRealm;
    }
    //3:配置缓存验证器
    @Bean
    public CacheManager cacheManager(){
        return new MemoryConstrainedCacheManager();
    }
    //4:配置记住我Cookie对象参数，rememberMeCookie()方法是设置Cookie的生成模版，比如cookie的name，cookie的有效时间等等。
    public SimpleCookie rememberMeCookie() {
        //这个参数是cookie的名称，对应前端的checkbox的name=rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //cookie生效时间为10秒
        simpleCookie.setMaxAge(10);
        return simpleCookie;
    }
    //5:配置Cookie管理对象，rememberMeManager()方法是生成rememberMe管理器，而且要将这个rememberMe管理器设置到securityManager中
    @Bean
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return  cookieRememberMeManager;
    }
    //6:注入自定义记住我过滤器
    @Bean
    public MyRememberFilter MyRememberFilter(){
        return new MyRememberFilter();
    }

    @Bean("sessionManager")
    public SessionManager sessionManager(){ //RedisSessionDao redisSessionDao
        MyWebSessionManager sessionManager = new MyWebSessionManager();
        sessionManager.setSessionValidationSchedulerEnabled(true);
//        sessionManager.setSessionIdUrlRewritingEnabled(false);
        sessionManager.setGlobalSessionTimeout(12*60*60*1000);
        //sessionManager.setSessionIdCookieEnabled(false);

        //sessionManager.setSessionDAO(redisSessionDao);// session存储的实现
        sessionManager.setDeleteInvalidSessions(true);// 是否在会话过期后会调用SessionDAO的delete方法删除会话 默认true

        Cookie sessionIdCookie = new SimpleCookie("SHAREJSESSIONID_MANAGE");
        sessionIdCookie.setPath("/");// jsessionId的path为 / 用于多个系统共享jsessionId
        sessionIdCookie.setHttpOnly(true);
        sessionManager.setSessionIdCookie(sessionIdCookie);// sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID

        return sessionManager;
    }

    //7:配置securityManager安全管理器，主要起到一个桥梁作用。
    @Bean("securityManager")
    public SecurityManager securityManager(@Qualifier("myRealm") MyRealm myRealm, SessionManager sessionManager) {
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        //注入自定义myRealm
        defaultWebSecurityManager.setRealm(myRealm);
        defaultWebSecurityManager.setCacheManager(cacheManager());
        defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
        defaultWebSecurityManager.setSessionManager(sessionManager);
        return defaultWebSecurityManager;
    }
    //8:进行全局配置，Filter工厂。设置对应的过滤条件和跳转条件，有自定义的过滤器，有shiro认证成功后，失败后，退出后等跳转的页面，有静态页面等内容的权限范围
    @Bean("shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager) {
        //shiro对象
        ShiroFilterFactoryBean bean= new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/index");

        Map<String,Filter> filterMap=new LinkedHashMap<>();
        filterMap.put("MyrememberFilter",MyRememberFilter());

        LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<String, String>();
        //认证顺序是从上往下执行
        linkedHashMap.put("/logout", "logout");//在这儿配置登出地址，不需要专门去写控制器。
        linkedHashMap.put("/static/**", "anon");
        //开启注册页面不需要权限
        linkedHashMap.put("/register", "anon");
        linkedHashMap.put("/saveregister", "anon");
        //验证phone唯一
        linkedHashMap.put("/solephone", "anon");
        //获取验证码
        linkedHashMap.put("/getcode", "anon");
        //验证码判断
        linkedHashMap.put("/comparecode", "anon");
        linkedHashMap.put("/websocket", "anon");//必须开启。
        linkedHashMap.put("/css/**", "anon");//不需要验证
        linkedHashMap.put("/js/**", "anon");//不需要验证
        //配置错误页面
        linkedHashMap.put("error", "anon");//不需要验证
        linkedHashMap.put("/img/**", "anon");//不需要验证
        linkedHashMap.put("/layui/**", "anon");//不需要验证
        linkedHashMap.put("/video/**", "anon");//不需要验证
        linkedHashMap.put("/bower_components/**", "anon");//不需要验证
        linkedHashMap.put("/plugins/**", "anon");//不需要验证
        linkedHashMap.put("/dist/**", "anon");//不需要验证
        linkedHashMap.put("/**", "user");//需要进行权限验证
        bean.setFilterChainDefinitionMap(linkedHashMap);
        return bean;
    }

    //9:配置shiro的生命周期
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    //10: 配置shiro注解是否生效
    //启动Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
    //配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor sourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        sourceAdvisor.setSecurityManager(securityManager);
        return sourceAdvisor;
    }
    //11:配置前台的shiro标签，使其能够使用
    *//*@Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }*//*
     */
}
